/*
 * 描          述:  <描述>
 * 修  改   人:  PengQingyang
 * 修改时间:  2022年4月26日
 * <修改描述:>
 */
package com.tx.component.sendsms.plugin.juhe;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

import org.springframework.http.HttpHeaders;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.tx.component.communication.exceptions.SendSMSException;
import com.tx.component.communication.model.SendResult;
import com.tx.component.sendsms.model.SendSMSWTChannelEnum;
import com.tx.component.sendsms.model.SendSMSWithTemplateRequest;
import com.tx.component.sendsms.plugin.SendSMSPlugin;
import com.tx.component.sendsms.plugin.SendSMSWithTemplateHandler;
import com.tx.core.exceptions.util.AssertUtils;

import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * 聚合短信发送插件<br/>
 * 接口备注：接口返回成功不代表接收成功,接口提交成功计费，具体接收状态只能由运营商查询；
 * 运营商限制同1个号码同1个签名的内容1分钟内只能接收1条，10分钟3条,1小时内4条，一天20条，
 * 否则可能会被运营商屏蔽，短信api接口本身不限制发送频率，具体发送频率需要用户自行设置，只限国内手机号。
 * 请务必添加图片验证码等防恶意攻击的机制，以防短信轰炸,营销内容最后加回T退订，营销短信发送时间为：8：30至21:30。营销内容有防钓鱼机制，请勿单条发送，移动20条起(循环调用)，联电不限制。
 * ,字数限制：短信内容（包含签名）小于等于70个字符为计费1条。超过70个字符为长短信，按每67个字
 * 
 * @author  PengQingyang
 * @version  [版本号, 2022年4月26日]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
public class JuheSendSMSPlugin extends SendSMSPlugin<JuheSendSMSPluginConfig>
        implements SendSMSWithTemplateHandler {
    
    /** 默认的链接超时时间 */
    private static final int DEFAULT_CONNNECT_TIMEOUT = 15 * 1000;
    
    /** 默认的读取超时时间 */
    private static final int DEFAULT_READ_TIMEOUT = 20 * 1000;
    
    /** 发送短信的url */
    public static final String SERVER_URL = "http://v.juhe.cn/sms/send";
    
    /** defaultUserAgent */
    public static String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.66 Safari/537.36";
    
    /** okhttp客户端 */
    private OkHttpClient client;
    
    /**
     * @throws Exception
     */
    @Override
    protected void doInit() throws Exception {
        this.client = new OkHttpClient.Builder()
                .connectTimeout(DEFAULT_CONNNECT_TIMEOUT, TimeUnit.MILLISECONDS)
                .writeTimeout(DEFAULT_READ_TIMEOUT, TimeUnit.MILLISECONDS)
                .readTimeout(DEFAULT_READ_TIMEOUT, TimeUnit.MILLISECONDS)
                .retryOnConnectionFailure(true)
                .build();
    }
    
    /**
     * @return
     */
    @Override
    public String getPrefix() {
        return "plugin.sendSMS.juhe";
    }
    
    /**
     * @return
     */
    @Override
    public String getName() {
        return "聚合短信插件";
    }
    
    /**
     * @return
     */
    @Override
    public String getVersion() {
        return "1.0";
    }
    
    /**
     * @return
     */
    @Override
    public int getOrder() {
        JuheSendSMSPluginConfig config = getConfig();
        return config.getPriorty();
    }
    
    /**
     * @param request
     * @return
     */
    @Override
    public boolean supports(SendSMSWithTemplateRequest request) {
        if (SendSMSWTChannelEnum.JUHE.equals(request.getChannel())) {
            return true;
        }
        return false;
    }
    
    /**
     * @param request
     * @return
     */
    @Override
    public SendResult sendWithTemplate(SendSMSWithTemplateRequest request) {
        AssertUtils.notNull(request, "request is null.");
        AssertUtils.notNull(request.getChannel(), "request.channel is null.");
        
        //电话号码、模板号、签名不能为空
        AssertUtils.notEmpty(request.getPhoneNumbers(),
                "request.phoneNumbers is empty.");
        AssertUtils.notEmpty(request.getTemplateCode(),
                "request.pemplateCode is empty.");
        
        //构建post请求
        JuheSendSMSPluginConfig config = getConfig();
        RequestBody requestBody = (new FormBody.Builder())
                .add("mobile", request.getPhoneNumbers())
                .add("tpl_id", request.getTemplateCode())
                .add("vars", request.getTemplateParamJSONString())
                .add("key", config.getAppkey())
                .add("dtype", "json")
                .build();
        Request req = new Request.Builder().url(SERVER_URL)
                .addHeader(HttpHeaders.USER_AGENT, USER_AGENT)
                .post(requestBody)
                .build();
        try {
            Response response = this.client.newCall(req).execute();
            JSONObject jsonObj = JSON.parseObject(response.body().string());
            if (jsonObj.getInteger("error_code") == 0) {
                SendResult result = SendResult.newSuccess();
                
                JSONObject resultJson = jsonObj.getJSONObject("result");
                result.getAttributes().put("sid", resultJson.getString("sid"));
                result.getAttributes()
                        .put("count", resultJson.getInteger("count"));
                result.getAttributes().put("fee", resultJson.getInteger("fee"));
                return result;
            } else {
                SendResult result = SendResult
                        .newFail(jsonObj.getString("reason"));
                return result;
            }
        } catch (IOException e) {
            throw new SendSMSException(e.getMessage(), e);
        }
    }
    
    //public static void main(String[] args) throws IOException {
    //    //模板号： 245356
    //    //参数：    name=测试企业名称
    //    //key:  dd095a21cb94dd3379766e762728810d123321qQ
    //    //构建post请求
    //    Map<String, String> params = new HashMap<>();
    //    params.put("name", "测试企业名称");
    //    System.out.println(JSON.toJSONString(params));
    //    RequestBody requestBody = (new FormBody.Builder())
    //            .add("mobile", "18983379637")
    //            .add("tpl_id", "245356")
    //            .add("vars", JSON.toJSONString(params))
    //            .add("key", "dd095a21cb94dd3379766e762728810d123321qQ")
    //            .add("dtype", "json")
    //            .build();
    //    Request req = new Request.Builder().url(SERVER_URL)
    //            .addHeader(HttpHeaders.USER_AGENT, USER_AGENT)
    //            .post(requestBody)
    //            .build();
    //    
    //    OkHttpClient client = new OkHttpClient.Builder()
    //            .connectTimeout(DEFAULT_CONNNECT_TIMEOUT, TimeUnit.MILLISECONDS)
    //            .writeTimeout(DEFAULT_READ_TIMEOUT, TimeUnit.MILLISECONDS)
    //            .readTimeout(DEFAULT_READ_TIMEOUT, TimeUnit.MILLISECONDS)
    //            .retryOnConnectionFailure(true)
    //            .build();
    //    
    //    Response response = client.newCall(req).execute();
    //    JSONObject jsonObj = JSON.parseObject(response.body().string());
    //    if (jsonObj.getInteger("error_code") == 0) {
    //        SendResult result = SendResult.newSuccess();
    //        
    //        JSONObject resultJson = jsonObj.getJSONObject("result");
    //        result.getAttributes().put("sid", resultJson.getString("sid"));
    //        result.getAttributes().put("count", resultJson.getInteger("count"));
    //        result.getAttributes().put("fee", resultJson.getInteger("fee"));
    //        
    //        System.out.println(JSON.toJSONString(result));
    //    } else {
    //        SendResult result = SendResult.newFail(jsonObj.getString("reason"));
    //        System.out.println(JSON.toJSONString(result));
    //    }
    //}
    
}
